import { assert } from "cc";
import { IProtoDefine, SocketSchemaDecodeData, SocketSchemaProtoCoder } from "../../../sgame/Socket/ISocket";
import Proto from '../../../proto/proto.js';

/**
 * socket 的 protobuf 协议编码器, 适用于 websocket(websocket 数据以帧发送，这个编码器没解决粘包拆包)
 */
class PbProtoCoder extends SocketSchemaProtoCoder {

    // 协议大纲
    private schemas: Map<number, string> = new Map<number, string>();

    public registerSchemas(defines: IProtoDefine) {
        for (const protoName in defines) {
            let protoId = defines[protoName];
            assert(!this.schemas.has(protoId), `[ProtobufCoder] register error, protoId: ${protoId}, has already register.`);
            this.schemas.set(protoId, protoName);
        }
    }

    public encode(protoId: number, data?: any): Uint8Array {
        let msg: Proto.Msg = new Proto.Msg();
        msg.id = protoId;
        if (data) {
            assert(this.schemas.has(protoId), `[ProtobufCoder] encode error, protoId: ${protoId}, has not register.`);
            msg.data = Proto["CS_" + this.schemas.get(protoId)].encode(data).finish();
        }

        return Proto.Msg.encode(msg).finish();
    }

    public decode(data: ArrayBuffer): SocketSchemaDecodeData {
        let msg = Proto.Msg.decode(new Uint8Array(data));
        const protoId: number = msg.id;
        if (!msg.data || msg.data.length == 0) {
            return [protoId];
        }

        assert(this.schemas.has(protoId), `[ProtobufCoder] decode error, protoId: ${protoId}, has not register.`);

        return [
            protoId,
            Proto["SC_" + this.schemas.get(protoId)].decode(msg.data)
        ];
    }
}

const pbCoder = new PbProtoCoder();
export { pbCoder, PbProtoCoder };